﻿using System.Web;
using Sissonix.ExtRest.Configuration;
using Sissonix.ExtRest.Processors;
using System;
using Sissonix.ExtRest.Exception;
using Sissonix.ExtRest.WADL;

namespace Sissonix.ExtRest
{
    /// <summary>
    /// This class encapsulates everything about the incoming request
    /// as it pertains to REST and to ExtJs.  
    /// </summary>
    public class ExtRestContext
    {
        private int? _start;
        private int? _limit;
        private string _sort = "";
        private string _dir = "";
        private int? _domainID;
        private string _processingClass = "";
        private string _processingAssembly = "";
        private string _processingType = "";
        private string _host = "";
        private string _domainRoot = "";
        private string _domainRequest = "";
        private ResponseFormat _fmt = ExtRest.ResponseFormat.EXTJS_JSON;


        /// <summary>
        /// ID sent for the URL in standard REST format
        /// </summary>
        public int? DomainId { get { return _domainID; } }

        /// <summary>
        /// ExtJs DataStore starting records number (for use with paging grids)
        /// </summary>
        public int? Start { get { return _start; } }

        /// <summary>
        /// ExtJs DataStore number of records to return (used with start to return a page
        /// worth of data
        /// </summary>
        public int? Limit { get { return _limit; } }

        /// <summary>
        /// ExtJs DataStore field to sort on
        /// </summary>
        public string Sort { get { return _sort; } }

        /// <summary>
        /// ExtJs DataStore sorting direction (only used if a sort param is passed
        /// </summary>
        public string SortDirection { get { return _dir; } }

        /// <summary>
        /// The name of the class that processes this URL
        /// </summary>
        public string ProcessingClass { get { return _processingClass; } }

        /// <summary>
        /// The Assembly of the ProcessingClass that processes this URL
        /// </summary>
        public string ProcessingAssembly { get { return _processingAssembly; } }

        /// <summary>
        /// The Type of the ProcessingClass that processes this URL
        /// </summary>
        public string ProcessingType { get { return _processingType; } }

        /// <summary>
        /// Request Host variables (comes from HTTPRequest.Headers["Host"]
        /// </summary>
        public string Host { get { return _host; } }

        /// <summary>
        /// The path segment for all Rest calls to the site.  This is found
        /// in web.config as the pathSegment: <extRest pathSegment="rest"></extRest>
        /// </summary>
        public string RestRoot { get { return ExtRestConfig.Singleton.RestRoot; } }

        /// <summary>
        /// The path segment for all DomainRoot.  For instance, in the URL
        /// www.lp.com/rest/user/43, "user" would be the domainRoot.
        /// </summary>
        public string DomainRoot { get { return _domainRoot; } }

        
                /// <summary>
        /// Everything after the domain root portion of the URL.  For instance, for the URL
        /// www.lp.com/rest/user/login/4778, this would be login/4778
        /// </summary>
        public string DomainRequest { get { return _domainRequest; } }

        /// <summary>
        /// The returned format.  ExtJs needs JSON (which is ResponseFormat.ExtJson)
        /// </summary>
        public ResponseFormat ResponseFormat { get { return _fmt; } }

        /// <summary>
        /// Gets the apprpriate Rest processor to handle the incoming http request.
        /// </summary>
        /// <returns>IExtRestProcessor</returns>
        public IExtRestProcessor GetRequestProcessor()
        {
            try
            {
                var obj = System.Activator.CreateInstance(_processingAssembly, _processingType).Unwrap();
                return (IExtRestProcessor)obj;
            }
            catch (System.Exception e)
            {
                throw new RestException("Could not instantiate class '" + _processingClass + "'", e);
            }
        }

        public ExtRestContext()
        {
            /*  On the context.Request object, here's an example of what you'll find:
                Path=/rest/user/
                QueryString=_dc=12312351535&start=0&limit=10
                RawUrl=/rest/user/?_dc=12312351535&start=0&limit=10
                RequestType="GET"
                URL=http://localhost:28624/rest/user/?_dc=12312351535&start=0&limit=10
                Headers["Host"]=http://localhost:28624
             */
            string key = "";
            string val = "";
            HttpRequest req = HttpContext.Current.Request;

            for (int a = 0; a < req.QueryString.Count; a++)
            {
                key = req.QueryString.GetKey(a).ToLower();
                val = req.QueryString.Get(a).ToString();
                switch (key)
                {
                    case "start": _start = Int16.Parse(val); break;
                    case "limit": _limit = Int16.Parse(val); break;
                    case "sort": _sort = val; break;
                    case "dir": _dir = val; break;
                    case "id":
                        int i;
                        if (int.TryParse(val, out i)) 
                            _domainID = i;
                        break;
                }
            }

            string DELIM = ExtRest.StringExtensions.PATHDELIM;

            ExtRestConfig config = ExtRestConfig.Singleton;

            /*Example
             * URL: http://www.lp.com/rest/user/login/43?fmt=html
             * HttpRequest.RawUrl: /rest/user/login/43?fmt=html
             * _host = www.lp.com
             * _restRoot = rest
             * _fullRootPath = www.lp.com/rest
             * _domainRequest = login/43
             * _domainRoot = user
             * _domainID = 43
             */

            _host = req.Headers["Host"].FixPath();
            
            resource r = ExtRestConfig.Singleton.Application.GetResourceForPath(rawurl);

            _processingClass = ExtRestConfigDB.app.GetProcessingClassName(_domainRoot);
            if (_processingClass == "")
            {
                throw new RestException("Cannot find rest processing class for domain '" + _domainRoot + "'.");
                return;
            }
            string[] arr = _processingClass.Split(',');
            try
            {
                _processingType = arr[0];
                _processingAssembly = arr[1];
            }
            catch (System.Exception e)
            {
            }
        }
    }
}
